import numpy as np
import datetime,time
from loguru import logger
from fastapi import APIRouter,Depends,Request
from sqlalchemy import desc,and_,asc
from sqlalchemy.orm import Session
from db.mysql import get_db
from model.downmine_data import DownmineData
from model.equipment import Equipment
from vendor.library.many_points_stress.sort_point import process_wavelength_data
from vendor.library.many_points_stress.many_points_stress import calculate_stress_points
from vendor.extend.conversion import timestamp_to_datetime,calculate_time_difference
from model.equipment_sensor import EquipmentSensorTable
from model.equipment_drill import EquipmentDrill
from model.analysis_report import AnalysisReport,FormBody,generate_report
from vendor.extend.conversion import is_positive_integer,is_index_valid
from vendor.extend.courier import *


InspectionReport = APIRouter()


@InspectionReport.post('/generate')
def generate(itme:FormBody, request: Request,db: Session = Depends(get_db)):
    item_dict = itme.dict()
    # current_timestamp = datetime.datetime.now().timestamp()
    # print("当前时间戳:", int(current_timestamp))
    # one_week_ago = (datetime.datetime.now() - datetime.timedelta(days=7)).timestamp()
    # print("一周前的时间戳:", int(one_week_ago))
    current_timestamp=item_dict.get('end_time',0)
    one_week_ago=item_dict.get('start_time',0)
    if current_timestamp<=one_week_ago:
        return Error(msg='结束时间不能小于等于开始时间')

    drill_id=item_dict.get('drill_id',0)
    if not is_positive_integer(drill_id):
        return Error(msg='钻孔id参数错误')
    drill=db.query(EquipmentDrill.channel).filter_by(id=drill_id).first()
    if not drill:
        return Error(msg='钻孔不存在')

    last_list=db.query(DownmineData.line,DownmineData.data,DownmineData.create_time).filter(and_(DownmineData.create_time > one_week_ago,DownmineData.create_time < current_timestamp,DownmineData.line==drill.channel)).order_by(asc("id")).all()
    # 截取的初始波长 历史数据开始五分钟后第一条数据
    initial_wavelengths = [1529.948, 1533.435, 1540.348, 1536.698, 1547.937, 1543.769, 1551.826, 1555.261, 1558.858, 1562.280]
    # 传入的点数
    point_num = 10
    # 传入的光栅点比例系数（由深入浅）
    coefficients = [0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.1, 1.2, 1.3, 1.4]
    # 传入的设计波长 后台配置
    design_wavelengths = [1529.948, 1533.435,  1540.348, 1536.698, 1547.937, 1543.769, 1551.826, 1555.261, 1558.858, 1562.280]
    # 生成10个数组 计算数据
    raw_wavelength_data={}
    # 截取的初始波长 历史数据开始五分钟后第一条数据
    initial_wavelengths = [1529.948, 1533.435, 1540.348, 1536.698, 1547.937, 1543.769, 1551.826, 1555.261, 1558.858, 1562.280]
    channel_arr=[]
    data_obj={}
    initial_obj={}
    for num in last_list:
        channel=num.line
        if channel not in channel_arr:
            channel_arr.append(channel)

        if num.create_time > (one_week_ago+300) and channel not in initial_obj:
            initial_obj[channel]=num.data[0:point_num]

        if channel not in data_obj:
            data_obj[channel]=[]

        data_obj[channel].append({
            'line':num.line,
            'data':num.data[0:point_num],
            'create_time':num.create_time
        })

    query = db.query(EquipmentDrill,EquipmentSensorTable,Equipment).join(EquipmentDrill, EquipmentSensorTable.drill_id == EquipmentDrill.id).join(Equipment, Equipment.id == EquipmentSensorTable.equipment_id)
    sensor_list = query.filter(EquipmentDrill.channel.in_(channel_arr)).all()
    sensor_obj={}
    for drill,sensor,equ in sensor_list:
        # 获得所有光栅1设计波长λ
        wavelength_data = [row['wavelength'] for row in sensor.raster_data]
        # 每个光栅深度
        depth_data = [row['depth'] for row in sensor.raster_data]
        # 光栅1比例系数K λ
        factor_data = [row['factor'] for row in sensor.raster_data]
        sensor_obj[drill.channel]={
            'number':equ.number,
            'coal_thickness':equ.coal_thickness,
            'work_face_distance':equ.work_face_distance,
            'identifier':drill.identifier,
            'wavelength':wavelength_data,
            'depth':depth_data,
            'factor':factor_data
        }
    change_stress={} #应力变化数列
    stress_obj={}
    for key, value in sensor_obj.items():
        channel_num=key

        if key in data_obj:

            data_row=data_obj[key]
            initial_wavelengths=initial_obj[key]
            # 获得所有光栅1设计波长λ
            design_wavelengths=value['wavelength'][0:point_num]
            # 光栅1比例系数K λ
            coefficients=value['factor'][0:point_num]

            if key not in stress_obj:
                stress_obj[key]=[]
            if key not in change_stress:
                change_stress[key]=[]

            for info in data_row:

                raw_wavelength_data[key]=info['data']
                analysis_report, processed_data, need_analysis, abnormal_positions= process_wavelength_data(design_wavelengths, raw_wavelength_data, point_num, channel_num)
                # 计算调整后的值
                adjusted_values = calculate_stress_points(processed_data, initial_wavelengths, coefficients)
                last_stress=stress_obj[key][-1:]
                if last_stress:
                    previous_stress=last_stress[0]['stress']
                    array1 = np.array(previous_stress)
                    array2 = np.array(adjusted_values)
                    arr1_cleaned = np.where(array1 == None, np.nan, array1)
                    arr2_cleaned = np.where(array2 == None, np.nan, array2)

                    difference = arr1_cleaned - arr2_cleaned #应力差值
                    amplitude_stress=np.abs(difference).tolist() #应力差值转列表数据
                else:
                    previous_stress=[0 for _ in range(point_num)]
                    amplitude_stress=previous_stress
                stress_obj[key].append({
                    'line':info['line'],
                    'data':info['data'],
                    'stress':adjusted_values, #应力值
                    'previous_stress':previous_stress,
                    'amplitude_stress':amplitude_stress, #应力差值
                    'create_time':info['create_time']
                })
                change_stress[key].append(amplitude_stress)

    txt=''
    for key, value in stress_obj.items():
        np_stress=[]
        np_change=[] #应力变化速度
        for stress in value:
            amplitude_stress = [item for item in stress['amplitude_stress'] if item is not None]
            stress = [item for item in stress['stress'] if item is not None]
            np_change.append(amplitude_stress)
            np_stress.append(stress)

        drill=sensor_obj[key]
        depth=drill['depth'] #光栅点深度
        # 获取每列的最大值
        max_change = np.amax(np_change, axis=0)
        max_stress = np.amax(np_stress, axis=0)
        txt=''
        txt+=f"{drill['identifier']}号钻孔应力传感器应力监测时间范围涵盖 {timestamp_to_datetime(one_week_ago,'%Y年%m月%d日')} 至 {timestamp_to_datetime(current_timestamp,'%Y年%m月%d日')}，\n"
        txt+=f"总监测天数为 {calculate_time_difference(int(one_week_ago),int(current_timestamp),'days')} 天，\n"
        txt+=f"钻孔内共布置{len(depth)}个测点，\n"
        for index, dot in enumerate(depth):
            txt+=f"测点{(index+1)}深度为{dot}m，\n"

        for index, dot in enumerate(depth):
            txt+=f"光栅{(index+1)}（深度为{dot}m）最大应力为{max_stress[index]} MPa，\n"

        for index, dot in enumerate(depth):
            txt+=f"测点{(index+1)}当日变化速度最大值{max_change[index]} MPa/h，\n"
        txt+=f"大模型请注意，以上是{drill['number']}工作面的钻孔应力监测情况，2251工作面煤厚{drill['coal_thickness']}m，推进距离为{drill['work_face_distance']}m，请进行深度推理分析。\n"

        report=AnalysisReport(prompt=txt,create_time=int(time.time()))
        try:
            # 添加提示词
            db.add(report)
            db.flush()
            db.refresh(report)
            db.commit()
        except Exception as e:
            # 手动回滚会话并重新抛出异常
            db.rollback()
            logger.error("工作面信息 添加 出错:{}", e)
            return Error(msg='创建报告失败',data=str(e))

        ret_rep=generate_report(report.id)
        if ret_rep:
            domain = str(request.base_url)
            return Success(msg='报告生成成功',data={
                'http_path':domain+ret_rep['http_path']
            })
        else:
            return Error(msg='报告生成失败')

    return Success(msg='提示词生成成功')
